package jobs

import (
	"demodog.com/resk/core/envelopes"
	"demodog.com/resk/infra"
	"fmt"
	"github.com/go-redsync/redsync"
	"github.com/gomodule/redigo/redis"
	"github.com/sirupsen/logrus"
	"github.com/tietang/go-utils"
	"time"
)

type RefundExpiredJobStarter struct {
	infra.BaseStarter
	ticker *time.Ticker
	mutex  *redsync.Mutex
}

func (r *RefundExpiredJobStarter) Init(ctx infra.StarterContext) {
	d := ctx.Props().GetDurationDefault("jobs.refund.interval", time.Minute)
	r.ticker = time.NewTicker(d)
	maxIdle := ctx.Props().GetIntDefault("redis.maxIdle", 2)
	maxActive := ctx.Props().GetIntDefault("redis.maxActive", 5)
	timeout := ctx.Props().GetDurationDefault("redis.timeout", 20*time.Second)
	addr := ctx.Props().GetDefault("redis.addr", "127.0.0.1:6379")
	pools := make([]redsync.Pool, 0)
	pool := &redis.Pool{
		//最大空闲连接数
		MaxIdle: maxIdle,
		//最大活动连接数
		MaxActive: maxActive,
		//超时时间
		IdleTimeout: timeout,
		//创建连接
		Dial: func() (conn redis.Conn, e error) {
			return redis.Dial("tcp", addr)
		},
	}
	pools = append(pools, pool)
	rsync := redsync.New(pools)
	//获取IP
	ip, err := utils.GetExternalIP()
	if err != nil {
		ip = "127.0.0.1"
	}
	r.mutex = rsync.NewMutex(
		//名字
		"lock:RefundExpired",
		//过期时间，小于定时任务
		redsync.SetExpiry(50*time.Second),
		//重试次数
		redsync.SetRetryDelay(3),
		//创建分布式锁的 key 值
		redsync.SetGenValueFunc(func() (s string, e error) {
			now := time.Now()
			logrus.Infof("结点%s正在执行过期红包的退款任务.", ip)
			return fmt.Sprintf("%d:%s", now.Unix(), ip), nil
		}),
	)
}

func (r *RefundExpiredJobStarter) Start(ctx infra.StarterContext) {
	logrus.Info("RefundExpiredJobStarter start")
	//go func() {
	for {
		//每分钟执行一次
		c := <-r.ticker.C
		err := r.mutex.Lock()
		if err == nil {
			logrus.Debug("过期红包退款开始...", c)
			//红包过期退款的业务逻辑代码
			domain := envelopes.ExpiredEnvelopeDomain{}
			domain.Expired()
		} else {
			logrus.Info("已经有结点在运行该任务")
		}
		r.mutex.Unlock()
	}
	// }()
	//runtime.Gosched()
}

func (r *RefundExpiredJobStarter) Stop(ctx infra.StarterContext) {
	r.ticker.Stop()
}

func (r *RefundExpiredJobStarter) StartBlocking() bool {
	return true
}

//基于Redis锁的分布式任务
//Redis setnx 命令实现分布式锁
